﻿using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;

namespace Forum.Infrastructure.Util
{
    /// <summary>
    /// JWT是由 . 分割的三部分组成：
    /// 头部(Header)
    /// 载荷(Payload) : 这一部分是JWT主要的信息存储部分，其中包含了许多种的声明（claims）。
    /// 签名(Signature)：使用保存在服务端的秘钥对其签名，用来验证发送者的JWT的同时也能确保在期间不被篡改。
    /// </summary>
    public static class JwtTokenUtil
    {
        /// <summary>
        /// 创建token
        /// </summary>
        /// <param name="id">用户id</param>
        /// <param name="jwtSecurityKey">key</param>
        /// <param name="jwtKeyName">密钥名</param>
        /// <param name="expirs">token有效时间</param>
        /// <returns></returns>
        public static string CreateToken(string id, string jwtSecurityKey, string jwtKeyName, DateTime expirs)
        {
            var claims = new List<Claim>();
            claims.Add(new Claim(ClaimTypes.Name, id));
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtSecurityKey)); // 获取密钥
            var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); //凭证 ，根据密钥生成
                                                                                    //.NET Core’s JwtSecurityToken class takes on the heavy lifting and actually creates the token.

            /*
			 Claims (Payload)
				Claims 部分包含了一些跟这个 token 有关的重要信息。 JWT 标准规定了一些字段，下面节选一些字段:

				iss: The issuer of the token，token 是给谁的  发送者
				aud: 接收的
				sub: The subject of the token，token 主题
				exp: Expiration Time。 token 过期时间，Unix 时间戳格式
				iat: Issued At。 token 创建时间， Unix 时间戳格式
				jti: JWT ID。针对当前 token 的唯一标识
				除了规定的字段外，可以包含其他任何 JSON 兼容的字段。
			 */
            var token = new JwtSecurityToken(
                issuer: jwtKeyName,
                audience: jwtKeyName,
                claims: claims,
                expires: expirs,
                signingCredentials: creds
            );

            return new JwtSecurityTokenHandler().WriteToken(token);
        }


        public static (string token, string jwtId) CreateToken(string userId, string Audience, string SecurityKey, TimeSpan ExpiresIn)
        {
            var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(SecurityKey)); // 获取密钥
            var tokenDescriptor = new SecurityTokenDescriptor
            {
                Subject = new ClaimsIdentity(new[]
                {
                    new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString("N")),
                    new Claim(JwtRegisteredClaimNames.Sub, userId)
                }),
                Issuer = Audience,
                Audience = Audience,
                IssuedAt = DateTime.Now,
                NotBefore = DateTime.Now,
                Expires = DateTime.Now.Add(ExpiresIn),
                SigningCredentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256)
            };
            var jwtTokenHandler = new JwtSecurityTokenHandler();
            var securityToken = jwtTokenHandler.CreateToken(tokenDescriptor);
            var token = jwtTokenHandler.WriteToken(securityToken);

            return (token, securityToken.Id);
        }


        /// <summary>
        /// 读取token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        public static string ReadJwtToken(string token)
        {
            var jwtSecurityTokenHandler = new JwtSecurityTokenHandler();
            var readJwtToken = jwtSecurityTokenHandler.ReadJwtToken(token);
            var key = string.Empty;
            if (readJwtToken.Claims?.Count() > 0)
            {
                key = readJwtToken.Claims.Where(a => a.Type == ClaimTypes.Name).FirstOrDefault()?.Value;
            }

            return key;
        }


    }
}
